package com.yeyks.service.impl;

import com.yeyks.apppay.service.AlipayService;
import com.yeyks.apppay.service.WXAppPayService;
import com.yeyks.base.Arguments;
import com.yeyks.dal.dao.VipOrderMapper;
import com.yeyks.dal.domain.UserInfo;
import com.yeyks.dal.domain.VipOrder;
import com.yeyks.exception.ServiceException;
import com.yeyks.model.em.VipOrderStatus;
import com.yeyks.model.enums.PayTypeEnum;
import com.yeyks.model.enums.VipOrderEnum;
import com.yeyks.service.PayService;
import com.yeyks.service.UserInfoService;
import com.yeyks.service.VipOrderService;
import com.yeyks.util.Utility;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author fuchangshuai
 * @date 2019/3/15 12:31 PM
 */
@Slf4j
@Service
public class VipOrderServiceImpl implements VipOrderService {

    @Autowired
    private VipOrderMapper vipOrderMapper;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private WXAppPayService wxAppPayService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private PayService payService;

    @Value("${wx.app.vipNotifyUrl}")
    String vip_notify_url;

    /**
     * 用户充值
     *
     * @param userInfo
     * @param price
     * @param inviteId
     * @param type
     * @return
     */
    @Override
    public Map<String, String> vipPay(UserInfo userInfo, String inviteId, Integer price, String type, String ip) {

        VipOrder vipOrder = getVipOrder(userInfo, inviteId, price);
        String payInfo = null;
        if (type == null || PayTypeEnum.ALIPAY.desc().equals(type)) {
            payInfo = alipayService.vipAppPay(vipOrder.getOrderNo(), price);
            vipOrder.setPaymentMethod(1);
        }
        if (type == null || PayTypeEnum.WXPAY.desc().equals(type)) {
            payInfo = wxAppPayService.vipPay(price, vipOrder.getOrderNo(), ip);
            vipOrder.setPaymentMethod(0);
        }
        vipOrderMapper.insertReturnId(vipOrder);
        Map<String, String> map = new HashMap<>();
        map.put("orderNo", vipOrder.getOrderNo());
        map.put("payInfo", payInfo);
        return map;
    }

    /**
     * h5用户用户充值
     *
     * @param userInfo
     * @param price
     * @param inviteId
     * @param type
     * @param openId
     * @return
     */
    @Override
    public Map<String, Object> h5VipPay(UserInfo userInfo, String inviteId, Integer price, String type, String ip, String openId, Boolean flag) {


        VipOrder vipOrder = getVipOrder(userInfo, inviteId, price);
        Map<String, String> wxPayInfo;
        try {
            Utility.switchConfig(flag, payService.getEngine(), null);
            wxPayInfo = payService.wxPreOrder(
                    openId, "商品描述", price, vipOrder.getOrderNo(), ip,
                    vip_notify_url,
                    "JSAPI");
        } catch (Exception e) {
            log.info("微信JSAPI支付异常{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("支付异常");
        }

        if (PayTypeEnum.XCX.desc().equals(type)) {
            vipOrder.setPaymentMethod(4);
        }
        if (PayTypeEnum.GZH.desc().equals(type)) {
            vipOrder.setPaymentMethod(5);
        }
        vipOrderMapper.insertReturnId(vipOrder);
        Map<String, Object> map = new HashMap<>();
        map.put("orderNo", vipOrder.getOrderNo());
        map.put("payInfo", wxPayInfo);
        return map;
    }

    /**
     * 通过订单号查询订单
     *
     * @param outTradeNo
     * @return
     */
    @Override
    public VipOrder selectOrderByOrderNo(String outTradeNo) {
        return vipOrderMapper.selectOrderByOrderNo(outTradeNo);
    }

    /**
     * 处理充值回调
     *
     * @param orderNo
     * @param flag
     */
    @Transactional
    @Override
    public void payCallback(String orderNo, Boolean flag) {
        //通过订单号查询订单
        VipOrder vipOrder = vipOrderMapper.selectOrderByOrderNo(orderNo);
        int status = VipOrderStatus.postPay;
        //成功，修改订单状态,并发放vip券
        if (flag) {
            userInfoService.createVIP(vipOrder.getUserId(), vipOrder.getPayAmount());
        } else {
            status = VipOrderStatus.payFailed;
        }
        //修改订单的状态
        Integer res = vipOrderMapper.updateByOrderNoAndStatus(orderNo, status);
        if (res != 1) {
            log.info("充值更新订单状态失败");
        }

    }

    /**
     * 充值取消后去支付
     *
     * @param userInfo
     * @param orderNo
     * @param type
     * @param ip
     * @return
     */
    @Override
    public Map<String, String> goPay(UserInfo userInfo, String orderNo, String type, String ip) {
        //通过订单号查询订单
        VipOrder orderInfo = vipOrderMapper.selectOrderByOrderNo(orderNo);
        checkOrderInfo(userInfo, orderInfo);
        String payInfo = null;
        //支付宝
        if (type == null || type.equals(PayTypeEnum.ALIPAY.desc())) {
            payInfo = alipayService.vipAppPay(orderInfo.getOrderNo(), orderInfo.getPayAmount());
            orderInfo.setPaymentMethod(PayTypeEnum.ALIPAY.value());
        }
        //微信支付
        if (type != null && type.equals(PayTypeEnum.WXPAY.desc())) {
            payInfo = wxAppPayService.pay(orderInfo.getPayAmount(), orderNo, ip);
            orderInfo.setPaymentMethod(PayTypeEnum.WXPAY.value());
        }
        Map<String, String> map = new HashMap<>();
        map.put("payInfo", payInfo);
        return map;
    }

    private void checkOrderInfo(UserInfo userInfo, VipOrder orderInfo) {
        if (orderInfo == null) {
            throw new ServiceException("该订单不存在");
        }
        if (!orderInfo.getStatus().equals(VipOrderStatus.prePay)) {
            throw new ServiceException("该订单非待支付状态");
        }
        if (!orderInfo.getUserId().equals(userInfo.getId())) {
            throw new ServiceException("当前订单非本人");
        }
    }

    private VipOrder getVipOrder(UserInfo userInfo, String inviteId, Integer price) {

        String orderNo = Utility.getOrderNo();
        VipOrder vipOrder = new VipOrder();
        vipOrder.setOrderNo(orderNo);
        vipOrder.setPayAmount(price);
        vipOrder.setType(VipOrderEnum.VIPTEN.value());
        vipOrder.setOrderDesc(VipOrderEnum.VIPTEN.desc());
        vipOrder.setUserId(userInfo.getId());
        vipOrder.setStatus(VipOrderStatus.prePay);
        if (Arguments.notEmpty(inviteId)) {
            vipOrder.setInviteId(inviteId);
        }
        return vipOrder;
    }
}
